home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / USBSampleStorageDriver / StorageClassDriver / StorageClassDriver.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  37.9 KB  |  1,332 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        StorageClassDriver.c
  3.  
  4.     Contains:    Contains the state machine for configuring the interface,
  5.                 and all routines needed by the rest of the class driver.
  6.  
  7.     Version:    1.3
  8.  
  9.     Copyright:    © 1998-2000 by Apple Computer, Inc., all rights reserved.
  10. */
  11.  
  12. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  13.     includes
  14.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  15. #include <DriverGestalt.h>        // For interface type used in Name reg search.
  16. #include <DriverServices.h>
  17. #include <MacTypes.h>
  18. #include <USB.h>
  19.  
  20. #include "StorageClassPublicAPI.h"
  21. #include "StorageClassDriver.h"
  22.  
  23. // Includes for the Protocols
  24. #include "StorageClassCBIProtocol.h"
  25. #include "StorageClassBulkProtocol.h"
  26. #include "StorageDeviceConfiguration.h"
  27.  
  28. // The Wake workaround is to handle devices that do not respond favorably to
  29. // Suspend/Resume.  Usually these devices will reset to an un initialized state.
  30. // The wake workaround sends a command to the device to determine if it has reset
  31. // itself and therefore no longer has its address set.  The workaround will reset
  32. // the device and then reconfigure its interface.
  33. // Flag to turn wake workaround on and off
  34. #define DO_WAKE_WORKAROUND    true
  35.  
  36. // These states are used by StorageDeviceInitiateConfiguration
  37. enum
  38. {
  39.     kGetFullConfiguration = 1,
  40.     kSetConfig,
  41.     kFindStorageInterface,
  42.     kNewInterfaceRef,
  43.     
  44.     kStorageConfigureInterface,
  45.     kStorageFindInterruptPipe,
  46.     kStorageFindBulkInPipe,
  47.     kStorageFindBulkOutPipe,
  48.  
  49.     kStorageGetVendorDescriptorlength,
  50.     kStorageGetVendorDescriptorString,
  51.     kStorageGetProductDescriptorlength,
  52.     kStorageGetProductDescriptorString,
  53.     
  54.     kReturnFromDriver     = 0x1000,
  55.     kRetryTransaction     = 0x2000,
  56.     kCompletionPending     = 0x8000
  57. };
  58.  
  59. // Structure to hold our Globals
  60. struct StorageClassInfo 
  61. {
  62.     USBPB                                     usbPB;                    // Configuration block
  63.     USBPipeRef                                 interruptPipeRef;        // Interrupt pipe reference
  64.     USBPipeRef                                 readPipeRef;            // Bulk in pipe reference
  65.     USBPipeRef                                 writePipeRef;            // Bulk out pipe reference
  66.  
  67.     //    device: configuration and interface details
  68.     USBDeviceRef                            interfaceRef;            // USB device reference
  69.     USBDeviceRef                            deviceRef;                // USB device reference
  70.     UInt32                                    interfaceNumber;
  71.  
  72.     USBConfigurationDescriptorPtr             pFullConfigDescriptor;
  73.  
  74.     // These two fields are used by the driver to hold the entire descriptor structure that
  75.     // is returned from the drive during the device configuration sequence.  This is used
  76.     // when loaded as a device (not interface) driver and by the wake from sleep reset sequence.
  77.     USBConfigurationDescriptor                configDescriptor;
  78.     USBInterfaceDescriptor                    interfaceDescriptor[10];
  79.  
  80.     USBDeviceDescriptor                     deviceDescriptor;        // copy for local reference
  81.     USBInterfaceDescriptorPtr                pInterfaceDescriptor;    // copy for local reference
  82.  
  83.     Str255                                    usbVendorNameString;    // Name of vendor
  84.     Str255                                    usbProductNameString;    // Name of Product
  85.     
  86.     //    class driver async transactions
  87.     SInt32                                     retryCount;                // automatically retry transactions
  88.     
  89.     // Class Driver configuration information
  90.     UInt32                                    configurationStatus;    // Current state of configuration
  91.     Boolean                                    classInUse;                // Used in StorageClassDriverNotifyProc to prevent removal by expert
  92.     Boolean                                    ROMDriverLocked;        // Used in StorageClassDriverNotifyProc to prevent removal by expert
  93. };
  94. typedef struct StorageClassInfo    StorageClassInfo;
  95.  
  96. // Dispatch Table definitions for the Unit Table
  97. static UInt32     MyUSBGetVersion(void);
  98. static OSStatus StorageClassDriverInitialize(void);
  99. static OSStatus StorageClassDriverTerminate(void);
  100. static OSStatus StorageClassDriverControl(UInt32 theControlSelector, void *theControlData);
  101. static OSStatus StorageClassDriverStatus(UInt32 theInfoSelector, void *theInfo);
  102. static OSStatus StorageClassDriverExecuteCommand(StorageExecuteCommandPBPtr cmdPBPtr);
  103.  
  104. StorageClassDispatchTable TheAppleStorageClassDispatchTable =
  105. {
  106.     kDispatchTableVersion,
  107.     StorageClassDriverInitialize,
  108.     StorageClassDriverTerminate,
  109.     StorageClassDriverControl,
  110.     StorageClassDriverStatus,
  111.     StorageClassDriverExecuteCommand
  112. };
  113.  
  114. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  115.     globals
  116.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  117. static     StorageClassInfo            gStorageClassInfo;            // Holds all of the common items
  118. static     Boolean                        gBeenThereDoneThat = false;    // Flag indicating if this driver has been called before
  119. static     SInt8                        gInSleepReset = 0;            // Is the driver in the middle of an after sleep reset?
  120. static    StorageExecuteCommandPBPtr    gAfterSleepPBPtr = nil;        // The StorageExecuteCommandPBPtr we received in the middle of a sleep reset
  121.  
  122. #if (DO_WAKE_WORKAROUND==true)
  123. static     Boolean                        inReset = false;            // flag to indicate if the driver has already started a wakeup reset        
  124. #endif
  125.  
  126. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  127.     prototypes
  128.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  129. static Boolean                        ImmediateError(OSStatus err);
  130. static void                         ConvertUnicodeToASCII( UInt8 *stringBuffer );
  131. static void                         InitDescriptorStringPB(  USBPB *usbPB, UInt8 stringIndex, UInt8 *stringBuffer, UInt16 stringLength );
  132. static USBInterfaceDescriptorPtr    GetInterfaceDescriptor(    LogicalAddress pConfigDesc, UInt32 ReqInterface );
  133. static void                            StorageDeviceInitiateConfiguration(USBPB* pb);
  134. static void                            StorageDeviceConfigureCompletion(USBPB* pb);
  135. static Boolean                         IsThisTheBootDevice ( USBDeviceRef usbRefNum );
  136.  
  137. // Protos for the SUSPEND/RESUME problem
  138. static void StartResetDeviceAfterSleep( void );
  139. static void ResetDeviceAfterSleep( USBPB *usbPB );
  140. static void ResetDeviceAfterSleepCompletion( USBPB *usbPB );
  141.  
  142. //****************************************************************************************************
  143. //Accessors for Global Info
  144. UInt8 GetInterfaceSubclass( void )
  145. {
  146.     return gStorageClassInfo.pInterfaceDescriptor->interfaceSubClass;
  147. }
  148.  
  149. UInt32 GetInterfaceNumber( void )
  150. {
  151.     return gStorageClassInfo.interfaceNumber;
  152. }
  153.  
  154. USBDeviceRef GetInterfaceRef( void )            
  155. {
  156.     return gStorageClassInfo.interfaceRef;                // USB device reference
  157. }
  158.  
  159. USBPipeRef GetBulkInPipeRef( void )
  160. {
  161.     return gStorageClassInfo.readPipeRef;
  162. }
  163.  
  164. USBPipeRef GetBulkOutPipeRef( void )
  165. {
  166.     return gStorageClassInfo.writePipeRef;
  167. }
  168.  
  169. USBPipeRef GetInterruptPipeRef( void )
  170. {
  171.     return gStorageClassInfo.interruptPipeRef;
  172. }
  173.  
  174. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  175. {
  176.     USBCompletion     usbCompletion = paramblock->usbCompletion;
  177.     UInt32             usbRefcon = paramblock->usbRefcon;
  178.  
  179.     BlockZero( paramblock, sizeof(USBPB) );
  180.  
  181.     paramblock->pbLength                 = sizeof(USBPB);
  182.     paramblock->pbVersion                 = kUSBCurrentPBVersion;
  183.     paramblock->usbReference             = theDeviceRef;
  184.     paramblock->usbCompletion             = usbCompletion;
  185.     paramblock->usbRefcon                 = usbRefcon;
  186.     paramblock->usbStatus                = kRequestPending; // Set status to pending so we can when a request is complete
  187. }
  188.  
  189.  
  190. Boolean ImmediateError(OSStatus err)
  191. {
  192.     return((err != kUSBPending) && (err != noErr) );
  193. }
  194.  
  195. Boolean    IsThisASupportedProtocol( UInt8 theProtocol )
  196. {
  197.     if (( theProtocol == kProtocolCBI ) || ( theProtocol == kProtocolCBNoInterrupt ) || ( theProtocol == kProtocolBulkOnly))
  198.     {
  199.         // This is indeed a protocol the driver understands
  200.         return true;
  201.     }
  202.  
  203.     // The driver does not know of this protocol
  204.     return false;
  205. }
  206.  
  207. OSStatus ClearFeatureEndpointStall( USBPB *usbPB, USBPipeRef pipeRefForEndpoint, USBCompletion completionProc, UInt32 refCon)
  208. {
  209.     // Make sure that the Data Toggles are reset before doing the Clear Stall.
  210.     USBResetPipeByReference( pipeRefForEndpoint );
  211.     
  212.     InitParamBlock( pipeRefForEndpoint, usbPB);     // Read the Status from the interrupt
  213.     
  214.     usbPB->usb.cntl.BMRequestType    = USBMakeBMRequestType(kUSBNone, kUSBStandard, kUSBEndpoint);            
  215.     usbPB->usb.cntl.BRequest         = kUSBRqClearFeature;
  216.     usbPB->usb.cntl.WValue             = 0;
  217.     usbPB->usb.cntl.WIndex             = 0;
  218.     
  219.     usbPB->usbBuffer                 = nil;
  220.     usbPB->usbReqCount                 = 0;
  221.     usbPB->usbCompletion             = completionProc;
  222.     usbPB->usbRefcon                 = refCon;
  223.  
  224.     // If this is not the default pipe, let the 
  225.     // USB Expert figure out the endpoint number
  226.     if ( pipeRefForEndpoint != GetInterfaceRef())
  227.     {
  228.         usbPB->usbFlags             = kUSBNo5SecTimeout | kUSBAddressRequest;
  229.     }
  230.     
  231.     return USBDeviceRequest( usbPB );
  232. }
  233.  
  234. // Buffer must be at least 2 bytes
  235. OSStatus GetStatusEndpointStatus( USBPB *usbPB, USBPipeRef pipeRefForEndpoint, USBCompletion completionProc, Ptr Buffer, UInt32 refCon)
  236. {
  237.     InitParamBlock( pipeRefForEndpoint, usbPB);     // Read the Status from the interrupt
  238.     
  239.     usbPB->usb.cntl.BMRequestType     = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBEndpoint);            
  240.     usbPB->usb.cntl.BRequest         = kUSBRqGetStatus;
  241.     usbPB->usb.cntl.WValue             = 0;
  242.     usbPB->usb.cntl.WIndex             = 0;
  243.     
  244.     usbPB->usbBuffer                 = Buffer;
  245.     usbPB->usbReqCount                 = 2;
  246.     usbPB->usbCompletion             = completionProc;
  247.     usbPB->usbRefcon                 = refCon;
  248.     
  249.     // If this is not the default pipe, let the 
  250.     // USB Expert figure out the endpoint number
  251.     if ( pipeRefForEndpoint != GetInterfaceRef())
  252.     {
  253.         usbPB->usbFlags             = kUSBNo5SecTimeout | kUSBAddressRequest;
  254.     }
  255.     
  256.     return USBDeviceRequest( usbPB );
  257. }
  258.  
  259. void ConvertUnicodeToASCII( UInt8 *stringBuffer )
  260. {
  261.     UInt8    stringLength;
  262.     UInt8    loopCount;
  263.     
  264.     stringLength = stringBuffer[0]/2;
  265.     for (loopCount = 0; loopCount< stringLength; loopCount++)
  266.     {
  267.         stringBuffer[loopCount+1] = stringBuffer[(loopCount+1)*2];
  268.     }
  269.     
  270.     stringBuffer[0] = stringLength-1;
  271. }
  272.  
  273. void InitDescriptorStringPB( USBPB *usbPB, UInt8 stringIndex, UInt8 *stringBuffer, UInt16 stringLength)
  274. {
  275.     InitParamBlock( gStorageClassInfo.interfaceRef, usbPB);
  276.  
  277.     usbPB->usb.cntl.BMRequestType     = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBDevice);            
  278.     usbPB->usb.cntl.BRequest         = kUSBRqGetDescriptor;
  279.     usbPB->usb.cntl.WValue             = 0x0300 | stringIndex;
  280.     usbPB->usb.cntl.WIndex             = 0x409;
  281.     usbPB->usb.cntl.reserved4         = HostToUSBWord(stringLength);
  282.     
  283.     usbPB->usbBuffer                 = stringBuffer;
  284.     usbPB->usbReqCount                 = stringLength;
  285.  
  286.     usbPB->usbFlags                 = kUSBNo5SecTimeout;
  287. }
  288.  
  289. USBInterfaceDescriptorPtr GetInterfaceDescriptor( LogicalAddress pConfigDesc, UInt32 ReqInterface )
  290. {
  291.     UInt32                        totalLength;
  292.     void *                        pEndOfDescriptors;
  293.     USBInterfaceDescriptorPtr    pMyIntDesc;
  294.     USBDescriptorHeaderPtr        pCurrentDesc;
  295.     UInt32                        anAddress, anOffset;
  296.  
  297.     totalLength         =    ((USBConfigurationDescriptorPtr)pConfigDesc)->totalLength;
  298.     pEndOfDescriptors     =    (Ptr)pConfigDesc + totalLength;            // get the total length and add it to the start of the config space
  299.     pCurrentDesc         =    (USBDescriptorHeaderPtr)pConfigDesc;    // point the currentdesc to the start of the config space
  300.     
  301.     while (pCurrentDesc < pEndOfDescriptors)                        // as long as we haven't exhausted all the descriptors
  302.     {
  303.         if (pCurrentDesc->descriptorType == kUSBInterfaceDesc)        // look at the current descriptor
  304.         {
  305.             pMyIntDesc = (USBInterfaceDescriptorPtr)pCurrentDesc;    // if it's an interface descriptor
  306.             if (pMyIntDesc->interfaceNumber == ReqInterface)        // see if it's the request descriptor
  307.             {
  308.                 return pMyIntDesc;                                    // current descriptor pointer
  309.             }
  310.         }
  311.         
  312.         anAddress =        (unsigned long) pCurrentDesc;                // Nope, that either wasn't an interface descriptor
  313.         anOffset  =        (unsigned long) pCurrentDesc->length;
  314.         anAddress +=    anOffset;
  315.         pCurrentDesc =    (USBDescriptorHeaderPtr) anAddress;
  316.     }                                                                // or it was, but not the interface we're looking for.
  317.     
  318.     return nil;
  319. }
  320.  
  321. //****************************************************************************************************
  322. //
  323. //        StorageClassDriverAPI.c calls end up here...
  324. //
  325. //****************************************************************************************************
  326.  
  327. OSStatus StorageClassDriverInitialize(void)
  328. {
  329.     gStorageClassInfo.classInUse = true;
  330.     gInSleepReset = 0;
  331.     gAfterSleepPBPtr = nil;
  332.     return noErr;
  333. }
  334.  
  335. OSStatus StorageClassDriverTerminate(void)
  336. {
  337.     gStorageClassInfo.ROMDriverLocked = false;
  338.     gStorageClassInfo.classInUse = false;
  339.     return noErr;
  340. }
  341.  
  342. OSStatus StorageClassDriverControl(    UInt32 theControlSelector, void *theControlData)
  343. {
  344.     OSStatus        status;
  345.     
  346.     switch (theControlSelector)
  347.     {
  348.         case kUSBStorageControlAbortCommand:
  349.         {
  350.             if((gStorageClassInfo.pInterfaceDescriptor->interfaceProtocol == kProtocolBulkOnly) || (gStorageClassInfo.deviceDescriptor.protocol == kProtocolBulkOnly))
  351.             {
  352.                 status = StorageClassBulkOnlyAbortCommand( (StorageExecuteCommandPBPtr) theControlData );
  353.             }
  354.             else
  355.             {
  356.                 status = StorageClassCBIAbortCommand( (StorageExecuteCommandPBPtr) theControlData );
  357.             }
  358.         }
  359.         break;
  360.         
  361.         case kUSBStorageControlSetParentsRefNumber:
  362.         {
  363.             USBDeviceRef    theDeviceRef;
  364.             
  365.             theDeviceRef = *(USBDeviceRef *)theControlData;
  366.             
  367.             if ( theDeviceRef != 0 )
  368.             {
  369.                 // If the passed in reference is not zero, we are an interface driver
  370.                 // so we need to save the device ref of our parent node, else if it is
  371.                 // zero, we are a device driver and the deviceRef we have is valid.
  372.                 gStorageClassInfo.deviceRef = theDeviceRef;
  373.             }
  374.         }
  375.         break;
  376.         
  377.         default:
  378.         {
  379.             status = controlErr;
  380.         }
  381.         break;
  382.     }    
  383.  
  384.     return status;
  385. }
  386.  
  387.  
  388. OSStatus StorageClassDriverStatus(    UInt32 theInfoSelector, void *theInfo)
  389. {
  390.     OSStatus        status;
  391.  
  392.     switch (theInfoSelector)
  393.     {
  394.         case kUSBStorageStatusGetServicesStatus:        // Return the current confifuration status
  395.         {
  396.             if ( gInSleepReset == 1 )
  397.             {
  398.                 *((UInt32*) theInfo) = kUSBStorageServicesConfigureComplete;
  399.             }
  400.             else
  401.             {
  402.                 *((UInt32*) theInfo) = gStorageClassInfo.configurationStatus;
  403.             }
  404.             
  405.             status = noErr;
  406.         }
  407.         break;
  408.  
  409.         case kUSBStorageStatusGetRemovalStatus:
  410.         {
  411.             *((Boolean*) theInfo) = !gStorageClassInfo.classInUse;
  412.             status = noErr;
  413.         }
  414.         break;
  415.  
  416.         case kUSBStorageStatusGetVendorStringPtr:
  417.         {
  418.             if( PStrLen(gStorageClassInfo.usbVendorNameString) == 0 )
  419.             {
  420.                 *((StringPtr *) theInfo) = nil;
  421.             }
  422.             else
  423.             {
  424.                 *((StringPtr *) theInfo) = gStorageClassInfo.usbVendorNameString;
  425.             }
  426.             
  427.             status = noErr;
  428.         }
  429.         break;
  430.  
  431.         case kUSBStorageStatusGetProductStringPtr:
  432.         {
  433.             if( PStrLen(gStorageClassInfo.usbProductNameString) == 0 )
  434.             {
  435.                 *((StringPtr *) theInfo) = nil;
  436.             }
  437.             else
  438.             {
  439.                 *((StringPtr *) theInfo) = gStorageClassInfo.usbProductNameString;
  440.             }
  441.             
  442.             status = noErr;
  443.         }
  444.         break;
  445.  
  446.         case kUSBStorageStatusGetDeviceReleaseNumber:
  447.         {
  448.             *((UInt16 *) theInfo) = USBToHostWord (gStorageClassInfo.deviceDescriptor.devRel);
  449.             status = noErr;
  450.         }
  451.         break;
  452.  
  453.         default:
  454.         {
  455.             status = statusErr;
  456.         }
  457.         break;
  458.     
  459.     }    
  460.  
  461.     return status;
  462. }
  463.  
  464.  
  465. // All device requests come through here
  466. OSStatus StorageClassDriverExecuteCommand( StorageExecuteCommandPBPtr cmdPBPtr )
  467. {
  468.     OSStatus    status;
  469.  
  470.     if ( gInSleepReset == 1 )
  471.     {
  472.         // The class driver is currently in the middle of an
  473.         // after sleep reset sequence.  Save the parameter block
  474.         // for when it is done and tell the UT driver that it is pending.
  475. #if (DO_WAKE_WORKAROUND==true)
  476.         if (((( cmdPBPtr->flags & kStorageDataIn) == kStorageDataIn ) || (( cmdPBPtr->flags & kStorageDataOut) == kStorageDataOut )) && ( cmdPBPtr->expectedCount >= 0x0200L))
  477.         {
  478.             gAfterSleepPBPtr = cmdPBPtr;
  479.             cmdPBPtr->status = kRequestPending;
  480.             
  481.             if ( inReset == false )
  482.             {
  483.                 inReset = true;
  484.                 StartResetDeviceAfterSleep();
  485.             }
  486.             
  487.             return kRequestPending;
  488.         }
  489.         else
  490.         {
  491.             //gAfterSleepPBPtr = cmdPBPtr;
  492.             cmdPBPtr->status = ioErr;
  493.             return ioErr;
  494.         }
  495. #else
  496.         gAfterSleepPBPtr = cmdPBPtr;
  497.         cmdPBPtr->status = kRequestPending;
  498.         return kRequestPending;
  499. #endif
  500.     }
  501.  
  502.     // Make sure we have been able to configure the device
  503.     if ( gStorageClassInfo.configurationStatus != kUSBStorageServicesConfigureComplete )
  504.     {
  505.         return kClassNotConfiguredError;
  506.     }
  507.         
  508.     if((gStorageClassInfo.pInterfaceDescriptor->interfaceProtocol == kProtocolBulkOnly) || (gStorageClassInfo.deviceDescriptor.protocol == kProtocolBulkOnly))
  509.     {
  510.         status = StorageClassBulkOnlyExecuteCommand( cmdPBPtr );
  511.     }
  512.     else
  513.     {
  514.         status = StorageClassCBIExecuteCommand( cmdPBPtr );
  515.     }
  516.     
  517.     return status;
  518. }
  519.  
  520.  
  521. void StorageDeviceInitiateConfiguration(USBPB *usbPB)
  522. {
  523.     OSStatus myErr;
  524.  
  525.     switch(usbPB->usbRefcon & ~kRetryTransaction)
  526.     {    
  527.         case kGetFullConfiguration:
  528.         {
  529.             gStorageClassInfo.pFullConfigDescriptor = &gStorageClassInfo.configDescriptor;
  530.             InitParamBlock(gStorageClassInfo.deviceRef, usbPB);
  531.             
  532.             usbPB->usb.cntl.WIndex         =     0;
  533.             usbPB->usb.cntl.WValue         =     1;
  534.             usbPB->usbRefcon             |=    kCompletionPending;
  535.             usbPB->usbReqCount             =     sizeof(USBConfigurationDescriptor)+(sizeof(USBInterfaceDescriptor)*10);
  536.             usbPB->usbBuffer             =     gStorageClassInfo.pFullConfigDescriptor;
  537.             usbPB->usbCompletion         =     StorageDeviceConfigureCompletion;
  538.             
  539.             //myErr = USBGetFullConfigurationDescriptor(usbPB);
  540.             myErr = USBGetConfigurationDescriptor(usbPB);
  541.             if(ImmediateError(myErr))
  542.             {
  543.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  544.             }
  545.         }
  546.         break;
  547.  
  548.         case kSetConfig:
  549.         {
  550.             InitParamBlock(gStorageClassInfo.deviceRef, usbPB);
  551.             
  552.             usbPB->usb.cntl.WValue                 =    gStorageClassInfo.pFullConfigDescriptor->configValue;         // Use configuration ID value from descriptor
  553.             usbPB->usbRefcon                     |=     kCompletionPending;
  554.             usbPB->usbCompletion                 = StorageDeviceConfigureCompletion;
  555.             myErr = USBSetConfiguration(usbPB);
  556.             if(ImmediateError(myErr))
  557.             {
  558.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  559.             }
  560.         }
  561.         break;
  562.  
  563.         case kFindStorageInterface:
  564.         {
  565.             InitParamBlock(gStorageClassInfo.deviceRef, usbPB);
  566.             usbPB->usbClassType             = kDeviceClass;
  567.             usbPB->usbSubclass                 = kDeviceSubClass;
  568.             usbPB->usbRefcon                 |= kCompletionPending;
  569.             usbPB->usbCompletion             = StorageDeviceConfigureCompletion;
  570.             
  571.             myErr = USBFindNextInterface(usbPB);
  572.             if(ImmediateError(myErr))
  573.             {
  574.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  575.             }
  576.         }
  577.         break;
  578.             
  579.         case kNewInterfaceRef:
  580.         {
  581.             InitParamBlock(gStorageClassInfo.deviceRef, usbPB);
  582.             usbPB->usb.cntl.WIndex     =     gStorageClassInfo.interfaceNumber;
  583.             usbPB->usbRefcon         |=    kCompletionPending;
  584.             usbPB->usbCompletion     =     StorageDeviceConfigureCompletion;
  585.  
  586.             myErr = USBNewInterfaceRef(usbPB);
  587.             if(ImmediateError(myErr))
  588.             {
  589.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  590.             }
  591.         }
  592.         break;
  593.                 
  594.         case kStorageConfigureInterface:
  595.         {
  596.             InitParamBlock(gStorageClassInfo.interfaceRef, usbPB);
  597.  
  598.             usbPB->usbCompletion     =     StorageDeviceConfigureCompletion;
  599.             usbPB->usbRefcon         |=    kCompletionPending;
  600.                         
  601.             myErr = USBConfigureInterface(usbPB);
  602.             if (ImmediateError(myErr))
  603.             {
  604.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  605.             }
  606.         }
  607.         break;
  608.  
  609.         case kStorageFindInterruptPipe:
  610.         {
  611.             InitParamBlock(gStorageClassInfo.interfaceRef, usbPB);
  612.  
  613.             usbPB->usbFlags         =    kUSBIn;
  614.             usbPB->usbClassType     =    kUSBInterrupt;
  615.             usbPB->usbCompletion     =    StorageDeviceConfigureCompletion;
  616.             usbPB->usbRefcon         |=    kCompletionPending;
  617.  
  618.             myErr = USBFindNextPipe( usbPB );
  619.             if (ImmediateError(myErr))
  620.             {
  621.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  622.                 usbPB->usbRefcon = kReturnFromDriver;
  623.             }
  624.         }
  625.         break;
  626.         
  627.         case kStorageFindBulkInPipe:
  628.         {
  629.             InitParamBlock(gStorageClassInfo.interfaceRef, usbPB);
  630.  
  631.             usbPB->usbFlags         =    kUSBIn;
  632.             usbPB->usbClassType         =    kUSBBulk;
  633.             usbPB->usbCompletion     =    StorageDeviceConfigureCompletion;
  634.             usbPB->usbRefcon         |=    kCompletionPending;
  635.  
  636.             myErr = USBFindNextPipe( usbPB );
  637.             if (ImmediateError(myErr))
  638.             {
  639.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  640.                 usbPB->usbRefcon = kReturnFromDriver;
  641.             }
  642.         }
  643.         break;
  644.         
  645.         case kStorageFindBulkOutPipe:
  646.         {
  647.             InitParamBlock(gStorageClassInfo.interfaceRef, usbPB);
  648.  
  649.             usbPB->usbFlags         =    kUSBOut;
  650.             usbPB->usbClassType     =    kUSBBulk;
  651.             usbPB->usbCompletion     =    StorageDeviceConfigureCompletion;
  652.             usbPB->usbRefcon        |=    kCompletionPending;
  653.  
  654.             myErr = USBFindNextPipe( usbPB );
  655.             if (ImmediateError(myErr))
  656.             {
  657.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  658.                 usbPB->usbRefcon =    kReturnFromDriver;
  659.             }
  660.         }
  661.         break;
  662.         
  663.  
  664.         case kStorageGetVendorDescriptorlength:
  665.         {
  666.             InitDescriptorStringPB( usbPB, gStorageClassInfo.deviceDescriptor.manuIdx, gStorageClassInfo.usbVendorNameString, 2);
  667.             usbPB->usbRefcon         |=    kCompletionPending;
  668.             usbPB->usbCompletion     =     StorageDeviceConfigureCompletion;
  669.             myErr = USBDeviceRequest(usbPB);
  670.             if (ImmediateError(myErr))
  671.             {
  672.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  673.             }
  674.         }
  675.         break;
  676.         
  677.         case kStorageGetVendorDescriptorString:
  678.         {
  679.             UInt16    stringLength;
  680.             
  681.             stringLength = gStorageClassInfo.usbVendorNameString[0];
  682.             InitDescriptorStringPB( usbPB, gStorageClassInfo.deviceDescriptor.manuIdx, gStorageClassInfo.usbVendorNameString, stringLength);
  683.             usbPB->usbRefcon             |=    kCompletionPending;
  684.             usbPB->usbCompletion         =     StorageDeviceConfigureCompletion;
  685.             myErr = USBDeviceRequest(usbPB);
  686.             if (ImmediateError(myErr))
  687.             {
  688.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  689.             }
  690.         }
  691.         break;
  692.         
  693.         case kStorageGetProductDescriptorlength:
  694.         {
  695.             InitDescriptorStringPB( usbPB, gStorageClassInfo.deviceDescriptor.prodIdx, gStorageClassInfo.usbProductNameString, 2);
  696.             usbPB->usbRefcon             |=    kCompletionPending;
  697.             usbPB->usbCompletion         = StorageDeviceConfigureCompletion;
  698.             myErr = USBDeviceRequest(usbPB);
  699.             if (ImmediateError(myErr))
  700.             {
  701.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  702.             }
  703.         }
  704.         break;
  705.  
  706.         case kStorageGetProductDescriptorString:
  707.         {
  708.             UInt16    stringLength;
  709.             
  710.             stringLength = gStorageClassInfo.usbProductNameString[0];
  711.             InitDescriptorStringPB( usbPB, gStorageClassInfo.deviceDescriptor.prodIdx, gStorageClassInfo.usbProductNameString, stringLength);
  712.             usbPB->usbRefcon             |=    kCompletionPending;
  713.             usbPB->usbCompletion         = StorageDeviceConfigureCompletion;
  714.             myErr = USBDeviceRequest(usbPB);
  715.             if (ImmediateError(myErr))
  716.             {
  717.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  718.             }
  719.         }
  720.         break;
  721.  
  722.         case kReturnFromDriver:
  723.         break;
  724.             
  725.         default:
  726.         {
  727.             gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  728.             usbPB->usbRefcon = kReturnFromDriver;
  729.         }
  730.         break;
  731.     }
  732.  
  733. // At this point the control is returned to the system.  If a USB transaction
  734. // has been initiated, then it will call the Complete procs
  735. // (below) to handle the results of the transaction.
  736. }
  737.  
  738. void StorageDeviceConfigureCompletion(USBPB *usbPB)
  739. {
  740.     // We should only retry if the error is a USB transaction problem
  741.     // Device errors are handled outside of the state machine.
  742.     if ((usbPB->usbStatus != noErr) && (usbPB->usbStatus != kUSBPending))
  743.     {
  744.         usbPB->usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  745.         usbPB->usbRefcon |= kRetryTransaction;
  746.         gStorageClassInfo.retryCount--;
  747.         if (!gStorageClassInfo.retryCount)
  748.         {
  749.             gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  750.             usbPB->usbRefcon = kReturnFromDriver;
  751.             return;
  752.         }
  753.     }
  754.     else
  755.     {
  756.         usbPB->usbRefcon &= ~kRetryTransaction;
  757.         gStorageClassInfo.retryCount = kStorageRetryCount;
  758.     }
  759.  
  760.     if (usbPB->usbRefcon & kCompletionPending)             
  761.     {                                                
  762.         usbPB->usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  763.         switch(usbPB->usbRefcon)
  764.         {
  765.             case kGetFullConfiguration:
  766.             {
  767.                 usbPB->usbRefcon = kSetConfig;
  768.             }
  769.             break;
  770.                 
  771.             case kSetConfig:
  772.             {
  773.                 usbPB->usbRefcon                         =    kFindStorageInterface;
  774.             }
  775.             break;
  776.                 
  777.             case kFindStorageInterface:
  778.             {
  779.                 gStorageClassInfo.interfaceNumber         =    usbPB->usb.cntl.WIndex;
  780.                 gStorageClassInfo.pInterfaceDescriptor     =     GetInterfaceDescriptor(    gStorageClassInfo.pFullConfigDescriptor, gStorageClassInfo.interfaceNumber );
  781.                 usbPB->usbRefcon                         =    kNewInterfaceRef;
  782.             }
  783.             break;
  784.                 
  785.             case kNewInterfaceRef:
  786.             {
  787.                 gStorageClassInfo.interfaceRef             =    usbPB->usbReference;
  788.                 usbPB->usbRefcon                         =    kStorageConfigureInterface;
  789.             }
  790.             break;
  791.                 
  792.             case kStorageConfigureInterface:
  793.             {
  794.                 if((gStorageClassInfo.pInterfaceDescriptor->interfaceProtocol == kProtocolBulkOnly) || (gStorageClassInfo.deviceDescriptor.protocol == kProtocolBulkOnly))
  795.                 {
  796.                     // Since this is a Bulk Only device, do not look for interrupt
  797.                     gStorageClassInfo.interruptPipeRef     = 0;        // We have no interrupt, so set ref to zero
  798.                     usbPB->usbRefcon                     = kStorageFindBulkInPipe;
  799.                 }
  800.                 else
  801.                 {
  802.                     usbPB->usbRefcon                     = kStorageFindInterruptPipe;
  803.                 }
  804.             }
  805.             break;
  806.             
  807.             case kStorageFindInterruptPipe:
  808.             {
  809.                 gStorageClassInfo.interruptPipeRef         = usbPB->usbReference;
  810.  
  811. #if defined( FOR_VENDORSPECIFIC )
  812.                 usbPB->usbRefcon                         = kStorageFindBulkInPipe;
  813. #else                
  814.                 if(((gStorageClassInfo.pInterfaceDescriptor->interfaceProtocol == kProtocolCBI) || (gStorageClassInfo.deviceDescriptor.protocol == kProtocolCBI)) 
  815.                     && (gStorageClassInfo.interruptPipeRef == 0))
  816.                 {
  817.                     // This is a CBI device and must have an interrupt. If no Interrupt pipe could be 
  818.                     // opened, report an error and halt drive configuration.
  819.                     gStorageClassInfo.configurationStatus     = kUSBStorageServicesConfigureFailed;
  820.                     usbPB->usbRefcon                         = kReturnFromDriver;
  821.                 }
  822.                 else
  823.                 {
  824.                     usbPB->usbRefcon                         = kStorageFindBulkInPipe;
  825.                 }
  826. #endif /* FOR_VENDORSPECIFIC */
  827.             }
  828.             break;
  829.                 
  830.             case kStorageFindBulkInPipe:
  831.             {
  832.                 // Save the pipe reference
  833.                 gStorageClassInfo.readPipeRef    =     usbPB->usbReference;
  834.                 
  835.                 // Onto the next state
  836.                 usbPB->usbRefcon         = kStorageFindBulkOutPipe;
  837.             }
  838.             break;
  839.             
  840.             case kStorageFindBulkOutPipe:
  841.             {
  842.                 gStorageClassInfo.writePipeRef = usbPB->usbReference;
  843.                 
  844.                 if ( gStorageClassInfo.deviceDescriptor.manuIdx == 0 )
  845.                 {
  846.                     gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureComplete;        // Flag for client to determine that we are now configured
  847.                     usbPB->usbRefcon = kReturnFromDriver;
  848.                 }
  849.                 else
  850.                 {
  851.                     usbPB->usbRefcon =                    kStorageGetVendorDescriptorlength;
  852.                 }
  853.             }
  854.             break;
  855.             
  856.             case kStorageGetVendorDescriptorlength:
  857.             {
  858.                 usbPB->usbRefcon = kStorageGetVendorDescriptorString;
  859.             }
  860.             break;
  861.             
  862.             case kStorageGetVendorDescriptorString:
  863.             {
  864.                 ConvertUnicodeToASCII( gStorageClassInfo.usbVendorNameString );
  865.                 usbPB->usbRefcon = kStorageGetProductDescriptorlength;
  866.             }
  867.             break;
  868.             
  869.             case kStorageGetProductDescriptorlength:
  870.             {
  871.                 usbPB->usbRefcon = kStorageGetProductDescriptorString;
  872.             }
  873.             break;
  874.             
  875.             case kStorageGetProductDescriptorString:
  876.             {
  877.                 ConvertUnicodeToASCII( gStorageClassInfo.usbProductNameString );
  878.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureComplete;        // Flag for client to determine that we are now configured
  879.                 usbPB->usbRefcon = kReturnFromDriver;
  880.             }
  881.             break;
  882.             
  883.             default:
  884.             {
  885.                 if ( usbPB->usbStatus == noErr )
  886.                 {
  887.                     usbPB->usbRefcon = kReturnFromDriver;
  888.                 }
  889.             }
  890.             break;
  891.         }
  892.     }
  893.     
  894.     if ( usbPB->usbStatus == noErr )
  895.     {
  896.         if (!(usbPB->usbRefcon & kReturnFromDriver))
  897.         {
  898.             StorageDeviceInitiateConfiguration(usbPB);
  899.         }
  900.         else
  901.         {
  902.             if ( gInSleepReset == 1 )
  903.             {
  904.                 DecrementAtomic8( &gInSleepReset );
  905.                 if ( gInSleepReset < 0) 
  906.                 {
  907.                     gInSleepReset = 0;
  908.                 }
  909.  
  910.                 if ( gAfterSleepPBPtr != nil )
  911.                 {
  912.                     OSStatus status;
  913.  
  914.                     // We got a command during the reset, send it out now
  915.                     status = StorageClassDriverExecuteCommand( gAfterSleepPBPtr );
  916.                     if ( status != kRequestPending )
  917.                     {
  918.                         if(gAfterSleepPBPtr->completionProc != nil)
  919.                         {
  920.                             gAfterSleepPBPtr->status = kUSBInternalErr;
  921.                             (*gAfterSleepPBPtr->completionProc)( gAfterSleepPBPtr );
  922.                         }
  923.                     }
  924.         
  925.                     gAfterSleepPBPtr = nil;
  926.                 }
  927.             }
  928.         }
  929.     }
  930.     else
  931.     {
  932.         gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;
  933.         if ( gInSleepReset == 1 )
  934.         {
  935.             DecrementAtomic8( &gInSleepReset );
  936.             if ( gInSleepReset < 0) 
  937.             {
  938.                 gInSleepReset = 0;
  939.             }
  940.  
  941.             if ( gAfterSleepPBPtr != nil )
  942.             {
  943.                 if(gAfterSleepPBPtr->completionProc != nil)
  944.                 {
  945.                     gAfterSleepPBPtr->status = kUSBInternalErr;
  946.                     (*gAfterSleepPBPtr->completionProc)( gAfterSleepPBPtr );
  947.                 }
  948.  
  949.                 gAfterSleepPBPtr = nil;
  950.             }
  951.         }
  952.     }
  953. }
  954.  
  955. UInt32 MyUSBGetVersion(void)
  956. {
  957.     UInt32    version;
  958.     
  959.        if ((Ptr) USBGetVersion != (Ptr) kUnresolvedCFragSymbolAddress)
  960.               version = USBGetVersion();
  961.        else
  962.               version = 0;    // version of USB is less than 1.3
  963.        return version;
  964. }
  965.  
  966. void StorageDriverEntry( USBDeviceRef deviceRef, USBDeviceDescriptorPtr deviceDescriptorPtr, USBInterfaceDescriptorPtr pInterfaceDescriptor )
  967. {
  968.     if( gBeenThereDoneThat == false )
  969.     {
  970.         gBeenThereDoneThat = true;
  971.         
  972.         // Check for the correct version of the USB manager.
  973.         // We are ok with all version later than 1.3
  974.         if ((MyUSBGetVersion() & 0xffff0000) < kMinimumUSBMgrVersion)        // Wrong USB version number so do NOT continue
  975.         {
  976.             gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureFailed;        // Flag for client to determine that configuration failed
  977.             return ;
  978.         }
  979.         
  980.         // Initialize the global data structures
  981.         BlockZero(&gStorageClassInfo, sizeof(StorageClassInfo));
  982.         
  983.         gStorageClassInfo.retryCount             = kStorageRetryCount;
  984.         gStorageClassInfo.deviceDescriptor         = *deviceDescriptorPtr;        // keep a copy of the device descriptor
  985.         
  986.         // If we got loaded as an interface driver, save the interface descriptor and set our interface pointer
  987.         // to point to it.
  988.         if ( pInterfaceDescriptor != nil )
  989.         {
  990.             gStorageClassInfo.interfaceDescriptor[0] = *pInterfaceDescriptor;
  991.             gStorageClassInfo.pInterfaceDescriptor     = &gStorageClassInfo.interfaceDescriptor[0];
  992.         }
  993.         else
  994.         {
  995.             gStorageClassInfo.pInterfaceDescriptor     = nil;
  996.         }
  997.         
  998.         gStorageClassInfo.deviceRef             = deviceRef;
  999.         gStorageClassInfo.interfaceRef             = deviceRef;
  1000.         
  1001.         InitParamBlock( deviceRef, &gStorageClassInfo.usbPB );
  1002.                 
  1003.         //    Start out at first state
  1004.         if (gStorageClassInfo.pInterfaceDescriptor != nil)
  1005.         {
  1006.             gStorageClassInfo.usbPB.usbRefcon = kStorageConfigureInterface;
  1007.         }
  1008.         else
  1009.         {
  1010.             gStorageClassInfo.usbPB.usbRefcon = kGetFullConfiguration;
  1011.         }
  1012.         
  1013.         gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureInProgress;
  1014.         StorageDeviceInitiateConfiguration(&gStorageClassInfo.usbPB);
  1015.     }
  1016. }
  1017.  
  1018.  
  1019. void StorageClassDriverFinalize( void )
  1020. {
  1021.     OSStatus    status;
  1022.  
  1023.     TheAppleStorageClassDispatchTable.dispatchTableVersion = 0;    
  1024.     
  1025.     //
  1026.     // Make sure all pipes are finished with transactions by calling the USBAbortPipeByReference function
  1027.     //
  1028.     status = USBAbortPipeByReference(gStorageClassInfo.interfaceRef);            // Control pipe
  1029.     status = USBAbortPipeByReference(gStorageClassInfo.interruptPipeRef);        // Interrupt pipe
  1030.     status = USBAbortPipeByReference(gStorageClassInfo.readPipeRef);            // Read pipe
  1031.     status = USBAbortPipeByReference(gStorageClassInfo.writePipeRef);            // Write pipe
  1032. }
  1033.  
  1034. OSStatus StorageClassDriverNotifyProc(UInt32 notification, void* pointer, UInt32 refcon)
  1035. {
  1036. #pragma unused ( pointer, refcon )
  1037.     OSStatus status = noErr;
  1038.         
  1039.     switch ( notification )
  1040.     {
  1041.         case kNotifyDriverBeingRemoved:
  1042.         {
  1043.             // We were in sleep and now we are being notified of being removed.
  1044.             // This means that we were probably hibernating.  Clear out the
  1045.             // sleep condition and if we received a command, return it with an error.
  1046.             DecrementAtomic8( &gInSleepReset );
  1047.             if ( gInSleepReset < 0 )
  1048.             {
  1049.                 gInSleepReset = 0;
  1050.             }
  1051.             
  1052.             if ( gAfterSleepPBPtr != nil )
  1053.             {
  1054.                 gStorageClassInfo.configurationStatus = kUSBStorageServicesTerminated;
  1055.                 if(gAfterSleepPBPtr->completionProc != nil)
  1056.                 {
  1057.                     gAfterSleepPBPtr->status = kUSBInternalErr;
  1058.                     (*gAfterSleepPBPtr->completionProc)( gAfterSleepPBPtr );
  1059.                 }
  1060.     
  1061.                 gAfterSleepPBPtr = nil;
  1062.                 status = kUSBDeviceBusy;
  1063.             }
  1064.             else if (gStorageClassInfo.configurationStatus == kUSBStorageServicesConfigureInProgress)
  1065.             {
  1066.                 // Don't allow removal if we are busy configuring the interface.
  1067.                 status = kUSBDeviceBusy;
  1068.             }
  1069.             else if (gStorageClassInfo.classInUse == true)
  1070.             {
  1071.                 // Don't allow removal until the UnitTable Driver says it's ok
  1072.                 status = kUSBDeviceBusy;
  1073.             }
  1074.             else
  1075.             {
  1076.                 status = noErr;
  1077.             }
  1078.         }
  1079.         break;
  1080.         
  1081.         case kNotifySystemSleepRequest:
  1082.         case kNotifySystemSleepDemand:
  1083.         {
  1084. #if (DO_WAKE_WORKAROUND==true)
  1085.             inReset = false;
  1086. #endif
  1087.             IncrementAtomic8( &gInSleepReset );
  1088.             if ( gInSleepReset > 1) 
  1089.             {
  1090.                 gInSleepReset = 1;
  1091.             }
  1092.  
  1093.             status = noErr;
  1094.         }
  1095.         break;
  1096.         
  1097.         case kNotifySystemSleepWakeUp:
  1098.         {
  1099. #if (DO_WAKE_WORKAROUND==true)
  1100.             if ( inReset == true )
  1101.             {
  1102.                 return noErr;
  1103.             }
  1104.             
  1105.             inReset = true;
  1106. #endif
  1107.             IncrementAtomic8( &gInSleepReset );
  1108.             if ( gInSleepReset > 1) 
  1109.             {
  1110.                 gInSleepReset = 1;
  1111.             }
  1112.             
  1113.             StartResetDeviceAfterSleep();
  1114.             status = noErr;
  1115.         }
  1116.         break;
  1117.         
  1118.         case kNotifySystemSleepRevoke:
  1119.         {
  1120.             DecrementAtomic8( &gInSleepReset );
  1121.             if ( gInSleepReset < 0 )
  1122.             {
  1123.                 gInSleepReset = 0;
  1124.             }
  1125.             
  1126.             if ( gAfterSleepPBPtr != nil )
  1127.             {
  1128.                 OSStatus status;
  1129.                 
  1130.                 // We got a command between the sleep notification and
  1131.                 // the sleep revoke notification, send it out now.
  1132.                 status = StorageClassDriverExecuteCommand( gAfterSleepPBPtr );
  1133.                 if ( status != kRequestPending )
  1134.                 {
  1135.                     if(gAfterSleepPBPtr->completionProc != nil)
  1136.                     {
  1137.                         gAfterSleepPBPtr->status = kUSBInternalErr;
  1138.                         (*gAfterSleepPBPtr->completionProc)( gAfterSleepPBPtr );
  1139.                     }
  1140.                 }
  1141.     
  1142.                 gAfterSleepPBPtr = nil;
  1143.             }
  1144.             
  1145.             status = noErr;
  1146.         }
  1147.         break;
  1148.         
  1149.         default:
  1150.         {
  1151.             // We don't know how to handle this request, return the appropriate error
  1152.             status = kUSBNotHandled;
  1153.         }
  1154.     }
  1155.     
  1156.     return status;
  1157. }
  1158.  
  1159. static UInt8    CntlStatus[2];
  1160.  
  1161. void StartResetDeviceAfterSleep( void )
  1162. {
  1163.     OSStatus    status;
  1164.  
  1165.     // First we'll do a GET_STATUS on the control endpoint to 
  1166.     // see if the device is still responding.  Use the interface reference 
  1167.     // because if the device behaves correctly, it will still be valid
  1168.     // else we will just get an error
  1169.     
  1170.     status = GetStatusEndpointStatus( &gStorageClassInfo.usbPB, GetInterfaceRef(), ResetDeviceAfterSleep, (Ptr) CntlStatus, 0); 
  1171.     if ( status != kUSBPending )
  1172.     {
  1173.         //USBExpertStatusLevel(1, gStorageClassInfo.deviceRef, "\pStorage Class: Immed error from GetStatus:" , status);
  1174.         gStorageClassInfo.usbPB.usbStatus = status;
  1175.         ResetDeviceAfterSleep( &gStorageClassInfo.usbPB );
  1176.     }
  1177. }
  1178.  
  1179. void ResetDeviceAfterSleep( USBPB *usbPB )
  1180. {
  1181.     OSStatus    status;
  1182.     
  1183.     status = usbPB->usbStatus;
  1184.     //USBExpertStatusLevel(1, GetInterfaceRef(), "\pStorage Class: Returned error from GetStatus:" , usbPB->usbStatus);
  1185.     if ( status != noErr )
  1186.     {
  1187.         // If we could not get the status of the control endpoint, the device 
  1188.         // must no longer be responding.  Time to do a reset.
  1189.         InitParamBlock( gStorageClassInfo.deviceRef, usbPB );
  1190.         
  1191.         usbPB->usbCompletion = ResetDeviceAfterSleepCompletion;
  1192.         status = USBResetDevice( usbPB );
  1193.         //USBExpertStatusLevel(1, GetInterfaceRef(), "\pStorage Class: Immed error from Reset:" , status);
  1194.     }
  1195.  
  1196.     // Either the Get_Status succeeded, or the USBResetDevice failed.  In either case, we want
  1197.     // to clear the sleep condition and if we received a command, process it now.
  1198.     if ( status != kUSBPending )
  1199.     {
  1200.         DecrementAtomic8( &gInSleepReset );
  1201.         if ( gInSleepReset < 0) 
  1202.         {
  1203.             gInSleepReset = 0;
  1204.         }
  1205.  
  1206.         if ( gAfterSleepPBPtr != nil )
  1207.         {
  1208.             OSStatus status;
  1209.             
  1210.             // We got a command during the reset, send it out now
  1211.             status = StorageClassDriverExecuteCommand( gAfterSleepPBPtr );
  1212.             if ( status != kRequestPending )
  1213.             {
  1214.                 if(gAfterSleepPBPtr->completionProc != nil)
  1215.                 {
  1216.                     gAfterSleepPBPtr->status = kUSBInternalErr;
  1217.                     (*gAfterSleepPBPtr->completionProc)( gAfterSleepPBPtr );
  1218.                 }
  1219.             }
  1220.  
  1221.             gAfterSleepPBPtr = nil;
  1222.         }
  1223.     }
  1224. }
  1225.  
  1226. void ResetDeviceAfterSleepCompletion( USBPB *usbPB )
  1227. {
  1228.     //USBExpertStatusLevel(1, GetInterfaceRef(), "\pStorage Class: Returned error from Reset:" , usbPB->usbStatus);
  1229.     // If no error occurs, reconfigure the device.  If an error occurred,
  1230.     // do nothing because there isn't anything that can be done.
  1231.     if ( usbPB->usbStatus == noErr )
  1232.     {
  1233.         //    Start out at first state and reconfigure the device
  1234.         BlockZero( &gStorageClassInfo.usbPB, sizeof(USBPB)); 
  1235.         gStorageClassInfo.usbPB.usbRefcon = kGetFullConfiguration;
  1236.         gStorageClassInfo.configurationStatus = kUSBStorageServicesConfigureInProgress;
  1237.         StorageDeviceInitiateConfiguration(&gStorageClassInfo.usbPB);
  1238.     }
  1239.     else
  1240.     {
  1241.         DecrementAtomic8( &gInSleepReset );
  1242.         if ( gInSleepReset < 0) 
  1243.         {
  1244.             gInSleepReset = 0;
  1245.         }
  1246.  
  1247.         if ( gAfterSleepPBPtr != nil )
  1248.         {
  1249.             if(gAfterSleepPBPtr->completionProc != nil)
  1250.             {
  1251.                 gAfterSleepPBPtr->status = kUSBInternalErr;
  1252.                 (*gAfterSleepPBPtr->completionProc)( gAfterSleepPBPtr );
  1253.             }
  1254.  
  1255.             gAfterSleepPBPtr = nil;
  1256.         }
  1257.     }
  1258. }
  1259.  
  1260. #pragma mark --
  1261. #pragma mark Name Registry Support Functions
  1262.  
  1263. Boolean IsThisTheBootDevice ( USBDeviceRef usbRefNum )
  1264. {
  1265.     RegEntryID                        chosenEntry;
  1266.     RegPropertyValueSize            size;
  1267.     RegPropertyNameBuf                propertyName;
  1268.     OSErr                            err;
  1269.     Boolean                            returnValue = false;
  1270.     OSType                             interfaceType; 
  1271.     DriverGestaltDeviceReferenceResponse deviceRef;
  1272.     
  1273.     RegistryEntryIDInit (&chosenEntry);
  1274.     err = RegistryCStrEntryLookup (nil, "Devices:device-tree:chosen", &chosenEntry);
  1275.     if (err == noErr) 
  1276.     {
  1277.         // We were able to find the chosen node, now look for the interface type property.
  1278.         CStrCopy (propertyName, "AAPL,bootpath-interfaceType");
  1279.         
  1280.         // See if property exists
  1281.         err = RegistryPropertyGetSize (&chosenEntry, propertyName, &size);
  1282.         if (err == noErr)
  1283.         {
  1284.             // The property exist, get its value.
  1285.             size = sizeof (interfaceType);
  1286.             err = RegistryPropertyGet (&chosenEntry, propertyName, &interfaceType, &size );
  1287.         }
  1288.         else
  1289.         {
  1290.             // There is no Interface type property, which means that we are not in the boot driver stack.
  1291.             RegistryEntryIDDispose (&chosenEntry);
  1292.             return false;
  1293.         }
  1294.  
  1295.         if ( interfaceType != kdgUSBIntf )
  1296.         {
  1297.             // The interface type is not USB, therefore, we are not in the boot driver stack.
  1298.             RegistryEntryIDDispose (&chosenEntry);
  1299.             return false;
  1300.         }
  1301.         
  1302.         // Now look for the device reference property.
  1303.         CStrCopy (propertyName, "AAPL,bootpath-deviceReference");
  1304.         
  1305.         // See if property exists
  1306.         err = RegistryPropertyGetSize (&chosenEntry, propertyName, &size);
  1307.         if (err == noErr)
  1308.         {
  1309.             // The property exist, get its value.
  1310.             size = sizeof (DriverGestaltDeviceReferenceResponse);
  1311.             err = RegistryPropertyGet (&chosenEntry, propertyName, &deviceRef, &size);
  1312.         }
  1313.         else
  1314.         {
  1315.             // There is no device reference property, which means that we are not in the boot driver stack.
  1316.             return false;
  1317.         }
  1318.         if ( usbRefNum != deviceRef.usbRef )
  1319.         {
  1320.             // The device reference found does not match this driver, we are not in the boot driver stack.
  1321.             RegistryEntryIDDispose (&chosenEntry);
  1322.             return false;
  1323.         }
  1324.         
  1325.         RegistryEntryIDDispose (&chosenEntry);
  1326.         
  1327.         // If we made it here, then this is indeed the boot driver.
  1328.         returnValue = true;
  1329.     }
  1330.     
  1331.     return returnValue;
  1332. }